#' 中介MR分析（多变量法）
#'
#' @param EO_res 暴露到结局的res
#' @param mv_res 暴露和中介到结局的多变量的mv_res
#'
#' @return 中介效应
#' @export
#'
#' @examples
#'
#' \dontrun{
#'
#' # propagation of errors method 误差传播法计算
#' # 此功能只可用于单暴露，单中介，单结局
#'
#' # https://www.nature.com/articles/s42003-022-03272-5
#'
#' library(Oneclick)
#'
#'
#' exposure<- c('finn-b-HYPOTHYROIDISM')
#'
#' mediation <- "F:/BaiduNetdiskDownload/1400种代谢物/GCST90200053.parquet"
#'
#' outcome <- 'ebi-a-GCST90001390'
#'
#'
#' # 总效应 EO_res
#'
#' exp_IVs<- U2_extract_instruments(exposure)
#' Outs<- U3_extract_outcomes_data(outcome = outcome ,exposure_iv = exp_IVs )
#' EO_dat<- U4_harmonise_data(exp_IVs,Outs)
#' EO_res<-U5_mr(EO_dat,run_mr_presso = FALSE,workers = 1)
#'
#'
#' # 暴露和中介的mv_res
#'
#' mv_exposures <- M1_mv_extract_exposures(list(exposure,mediation))
#' mv_outcome <- M2_mv_extract_outcome( outcome = outcome,
#'                                      mv_exposures = mv_exposures)
#' mv_dat<-M3_mv_harmonise_data( mv_exposures = mv_exposures,
#'                               mv_outcome = mv_outcome )
#'
#'
#' # TwoSampleMR给出的IVW MVMR 的结果
#' mv_res<- TwoSampleMR::mv_multiple(mv_dat)[["result"]] %>%
#'   TwoSampleMR::generate_odds_ratios()
#'
#'
#' mediation_effect<-M8_difference_mediation(EO_res,mv_res )
#'
#'
#'
#'
#' }
#'
#'
M8_difference_mediation<-function(EO_res,mv_res){

  # 总效应，就是暴露到结局
  exposure_total_beta <- ifelse(!is.na(EO_res$`b_Inverse variance weighted`),
                                EO_res$`b_Inverse variance weighted`,
                                EO_res$`b_Wald ratio`)
  exposure_total_se <- ifelse(!is.na(EO_res$`se_Inverse variance weighted`),
                              EO_res$`se_Inverse variance weighted`,
                              EO_res$`se_Wald ratio`)

  exposure_name<-EO_res$exposure[1]

  # 直接效应，多变量的暴露到结局
  direct_beta<-(subset( mv_res, exposure==exposure_name ))$b
  direct_se<-(subset( mv_res, exposure==exposure_name ))$se

  # 中介效应，也就是间接效应
  mediation_effect<-difference_method_PoE(exposure_total_beta,exposure_total_se,direct_beta,direct_se)


  mediation_effect$id.exposure <- EO_res$id.exposure
  mediation_effect$id.mediation <- ( subset( mv_res, !exposure==exposure_name ) )$id.exposure
  mediation_effect$id.outcome <- EO_res$id.outcome
  mediation_effect$exposure <- EO_res$exposure
  mediation_effect$mediation <- ( subset( mv_res, !exposure==exposure_name ) )$exposure
  mediation_effect$outcome <- EO_res$outcome

  mediation_effect <- mediation_effect %>% dplyr::select(id.exposure, id.mediation,id.outcome,
                                                         exposure, mediation,outcome,everything())

  message("使用误差传播法(propagation of errors method)计算中介效应(多变量法).
引用https://www.nature.com/articles/s42003-022-03272-5")

  return( mediation_effect )
}

difference_method_PoE <- function(total_beta, total_se, direct_beta, direct_se, verbose = F){
  # calculate indirect effect of exposure on outcome (via mediator)
  # i.e. how much mediator accounts for total effect of exposure on outcome effect

  # calculate indirect effect beta
  # INDIRECT = TOTAL (of exposure, univ) - DIRECT (of exposure, mvmr)
  indirect_beta = total_beta -  direct_beta
  #indirect_beta = round(indirect_beta,2)
  if (verbose) {print(paste("Indirect effect = ",
                            round(total_beta, 2)," - ", round(direct_beta, 2),
                            " = ", round(indirect_beta,2)))}


  # calculate SE of indirect effect
  ### using propagation of errors method
  # SE of INDIRECT effect (difference) = sqrt(SE TOTAL^2 + SE DIRECT^2)
  indirect_se = round(sqrt(total_se^2 + direct_se^2), 4)
  if (verbose) {print(paste("SE of indirect effect = sqrt(",
                            round(total_se, 2),"^2 + ", round(direct_se,2),
                            "^2) = ", indirect_se))}


  # put data into a tidy df
  df <-data.frame(b= indirect_beta,
                  se = indirect_se)
  df$pval = as.numeric(2 * stats::pnorm(abs( df$b/ df$se),lower.tail=FALSE))

  df<- TwoSampleMR::generate_odds_ratios(df)

  return(df)
}
